package com.gzc.just.play.last.war.sceneserver.skill;

import com.gzc.just.play.last.war.sceneserver.gameobject.unit.GameUnit;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 技能管理器 - 管理单位的所有技能
 *
 * 功能：
 * - 技能的学习和遗忘
 * - 技能的升级
 * - 技能的释放
 * - 冷却管理
 * - 技能查询
 *
 * 对应C++的 SSSkillMgr
 *
 * @author AI编程助手
 * @version 1.0
 * @since 2025-11-22
 */
public class SkillManager {
    
    private static final Logger log = LoggerFactory.getLogger(SkillManager.class);
    
    private final GameUnit owner;
    private final Map<Integer, Skill> skills = new HashMap<>(); // skillId -> Skill
    private final List<SkillListener> listeners = new CopyOnWriteArrayList<>();
    private long lastSkillCastTime = 0;
    
    /**
     * 创建技能管理器
     *
     * @param owner 技能所有者
     */
    public SkillManager(GameUnit owner) {
        this.owner = owner;
    }
    
    /**
     * 学习技能
     *
     * @param skill 要学习的技能
     */
    public void learnSkill(Skill skill) {
        if (skill == null) {
            log.warn("试图学习空技能");
            return;
        }
        
        int skillId = skill.getSkillId();
        if (skills.containsKey(skillId)) {
            log.warn("已经学过技能: {}", skillId);
            return;
        }
        
        skills.put(skillId, skill);
        log.debug("学习技能: {} ({})", skillId, skill.getName());
        notifySkillLearned(skill);
    }
    
    /**
     * 遗忘技能
     *
     * @param skillId 技能ID
     */
    public void forgetSkill(int skillId) {
        Skill skill = skills.remove(skillId);
        if (skill != null) {
            log.debug("遗忘技能: {} ({})", skillId, skill.getName());
            notifySkillForgotten(skill);
        }
    }
    
    /**
     * 获取技能
     *
     * @param skillId 技能ID
     * @return 技能对象，如果不存在返回null
     */
    public Skill getSkill(int skillId) {
        return skills.get(skillId);
    }
    
    /**
     * 升级技能
     *
     * @param skillId 技能ID
     * @param levelUp 升级数量
     */
    public void upgradeSkill(int skillId, int levelUp) {
        Skill skill = skills.get(skillId);
        if (skill == null) {
            log.warn("技能不存在: {}", skillId);
            return;
        }
        
        int oldLevel = skill.getSkillLevel();
        skill.upgradeSkill(levelUp);
        log.debug("升级技能 {} 从等级 {} 到 {}", skillId, oldLevel, skill.getSkillLevel());
        notifySkillUpgraded(skill, oldLevel);
    }
    
    /**
     * 检查是否可以释放技能
     *
     * @param skillId 技能ID
     * @return 如果可以释放，返回true
     */
    public boolean canCastSkill(int skillId) {
        Skill skill = skills.get(skillId);
        if (skill == null) {
            return false;
        }
        
        long currentTime = System.currentTimeMillis();
        return skill.canCast(currentTime, owner.getCurrentMana());
    }
    
    /**
     * 释放技能
     *
     * @param skillId 技能ID
     * @return 如果成功释放，返回true
     */
    public boolean castSkill(int skillId) {
        Skill skill = skills.get(skillId);
        if (skill == null) {
            log.warn("技能不存在: {}", skillId);
            return false;
        }
        
        long currentTime = System.currentTimeMillis();
        
        if (!skill.canCast(currentTime, owner.getCurrentMana())) {
            log.debug("无法释放技能 {} - 条件不满足", skillId);
            return false;
        }
        
        // 释放技能
        skill.cast(currentTime);
        
        // 消耗魔力
        int manaCost = skill.getManaCost();
        if (manaCost > 0) {
            owner.restoreMana(-manaCost);
        }
        
        this.lastSkillCastTime = currentTime;
        log.debug("释放技能: {} ({})", skillId, skill.getName());
        notifySkillCasted(skill);
        
        return true;
    }
    
    /**
     * 重置所有技能冷却
     */
    public void resetAllCooldowns() {
        for (Skill skill : skills.values()) {
            skill.resetCooldown();
        }
        log.debug("重置所有技能冷却");
    }
    
    /**
     * 重置指定技能的冷却
     *
     * @param skillId 技能ID
     */
    public void resetSkillCooldown(int skillId) {
        Skill skill = skills.get(skillId);
        if (skill != null) {
            skill.resetCooldown();
            log.debug("重置技能 {} 冷却", skillId);
        }
    }
    
    /**
     * 获取技能的剩余冷却时间
     *
     * @param skillId 技能ID
     * @return 剩余冷却时间（毫秒），如果技能不存在或不在冷却，返回0
     */
    public long getSkillCooldown(int skillId) {
        Skill skill = skills.get(skillId);
        if (skill == null) {
            return 0;
        }
        return skill.getRemainingCooldown(System.currentTimeMillis());
    }
    
    /**
     * 获取所有已学习的技能
     */
    public Collection<Skill> getAllSkills() {
        return new ArrayList<>(skills.values());
    }
    
    /**
     * 获取特定类型的技能列表
     *
     * @param skillType 技能类型
     */
    public List<Skill> getSkillsByType(SkillType skillType) {
        List<Skill> result = new ArrayList<>();
        for (Skill skill : skills.values()) {
            if (skill.getSkillType() == skillType) {
                result.add(skill);
            }
        }
        return result;
    }
    
    /**
     * 获取技能数量
     */
    public int getSkillCount() {
        return skills.size();
    }
    
    /**
     * 清除所有技能
     */
    public void clearAllSkills() {
        skills.clear();
        log.debug("清除所有技能");
    }
    
    /**
     * 添加技能事件监听器
     */
    public void addListener(SkillListener listener) {
        if (listener != null) {
            listeners.add(listener);
        }
    }
    
    /**
     * 移除技能事件监听器
     */
    public void removeListener(SkillListener listener) {
        listeners.remove(listener);
    }
    
    /**
     * 更新技能冷却
     *
     * @param currentTime 当前时间
     */
    public void updateCooldowns(long currentTime) {
        for (Skill skill : skills.values()) {
            skill.updateCooldown(currentTime);
        }
    }
    
    /**
     * 获取所有冷却的技能
     */
    public List<Skill> getSkillsInCooldown() {
        List<Skill> result = new ArrayList<>();
        long currentTime = System.currentTimeMillis();
        for (Skill skill : skills.values()) {
            if (skill.isInCooldown(currentTime)) {
                result.add(skill);
            }
        }
        return result;
    }
    
    /**
     * 获取最后一次释放技能的时间
     */
    public long getLastSkillCastTime() {
        return lastSkillCastTime;
    }
    
    /**
     * 获取上一个释放的技能
     */
    public Skill getLastCastedSkill() {
        long currentTime = System.currentTimeMillis();
        Skill lastSkill = null;
        long lastTime = 0;
        
        for (Skill skill : skills.values()) {
            if (skill.getLastCastTime() > lastTime) {
                lastTime = skill.getLastCastTime();
                lastSkill = skill;
            }
        }
        
        return lastSkill;
    }
    
    /**
     * 获取技能摘要信息
     */
    public String getSkillsSummary() {
        StringBuilder sb = new StringBuilder();
        sb.append("技能列表:\n");
        
        for (Skill skill : getAllSkills()) {
            long cooldown = skill.getRemainingCooldown(System.currentTimeMillis());
            sb.append(String.format("  - 等级%d %s (冷却: %dms, 魔力: %d)\n",
                skill.getSkillLevel(),
                skill.getName(),
                cooldown,
                skill.getManaCost()));
        }
        
        if (skills.isEmpty()) {
            sb.append("  (无技能)");
        }
        
        return sb.toString();
    }
    
    /**
     * 技能事件通知
     */
    private void notifySkillLearned(Skill skill) {
        for (SkillListener listener : listeners) {
            try {
                listener.onSkillLearned(skill);
            } catch (Exception e) {
                log.error("技能学习监听器异常", e);
            }
        }
    }
    
    private void notifySkillForgotten(Skill skill) {
        for (SkillListener listener : listeners) {
            try {
                listener.onSkillForgotten(skill);
            } catch (Exception e) {
                log.error("技能遗忘监听器异常", e);
            }
        }
    }
    
    private void notifySkillUpgraded(Skill skill, int oldLevel) {
        for (SkillListener listener : listeners) {
            try {
                listener.onSkillUpgraded(skill, oldLevel);
            } catch (Exception e) {
                log.error("技能升级监听器异常", e);
            }
        }
    }
    
    private void notifySkillCasted(Skill skill) {
        for (SkillListener listener : listeners) {
            try {
                listener.onSkillCasted(skill);
            } catch (Exception e) {
                log.error("技能释放监听器异常", e);
            }
        }
    }
}
